/**
 * idea工具集
 */
export { default as ideaTools } from "./utilsTools/ideaTools";
/**
 * tree工具集
 */
export { default as treeTools } from "./utilsTools/treeTools";
/**
 * 时间工具集
 */
export { default as timeTools } from "./utilsTools/timeTools";

/**
 * 校验工具集
 */
export { default as testTools } from "./utilsTools/testTools";

/**
 * schema解析相关的工具集
 */
export {default as schemaTools} from "./utilsTools/schemaTools";
////
import { globalConfig, resourceApiAliasConfig } from "./index";
/* 后端请求是否成功 */
export function isSuccessReqBackend(res) {
  return globalConfig.isSuccessReqBackend(res);
}

/** 后端请求错误信息 */
export function getErrorMsgReqBackend(res) {
  return globalConfig.getErrorMsgReqBackend(res);
}

/**
 * 获取后端列表型数据
 */
export function getBackendDataItems(res) {
  return globalConfig.getBackendDataItems(res);
}

/**
 * 获取后端数据
 */
export function getBackendData(res) {
  return globalConfig.getBackendData(res);
}
export async function fakerReqBackend() {
  return globalConfig.fakerReqBackend();
}

// 深拷贝
import { cloneDeep } from "lodash-es";
import { eq } from "lodash-es";
import { sampleSize } from "lodash-es";
const charSet_AZaz09 =
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const charSet_AZaz = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const getRandom = (obj = {}) => {
  const { type = "AZaz", len = 10 } = obj;
  const chartSet = type === "AZaz" ? charSet_AZaz : charSet_AZaz09;
  return sampleSize(chartSet, len).join("");
};
export { cloneDeep, eq, sampleSize, getRandom };

/**
 * 判断值具体类型
 * 所有检测类型结果枚举:  "date","regexp","array","object","number","string","null","undefined","function"
 */
export const u_getTypeof = (val) => {
  const s = Object.prototype.toString.call(val);
  return s.match(/\[object (.*?)\]/)[1].toLowerCase();
};
/* 判断字符串是否可以被序列化为json */
export const isJsonString = (str) => {
  try {
    if (typeof JSON.parse(str) == "object") {
      //console.log('是否true')
      return true;
    }
  } catch (e) {}
  return false;
};
/**
 * 前后端请求的字段映射;类型为数组对象的key的映射、类型为string的映射
 * @param {string} target "BackEnd": 分隔符命名 转 小驼峰; "FontEnd": 驼峰 转 分隔符
 * @param {string} safeKeys 即使 isRecursion = true,也不会递归修改key的
 * 其中后端 业务接口命名如果有 下划线 用于前端view源码目录层级创建
 * 后端list返回主键统一命名成id;
 * 
  hasChildren: 'hasChildren',
  children: 'children'

 *  */
export function mapKeysToTarget(
  data,
  target = "FontEnd",
  isRecursion = true,
  treeProps = {},
  safeKeys = ["uiOptions", "ui-options", "extraProperties", "extra-properties"]
) {
  //TODO:FIXME:强制camel写法//转到前端使用时是has-children
  const treePropsClone = cloneDeep(treeProps);
  target === "FontEnd"
    ? (treePropsClone.hasChildren = "hasChildren")
    : (treePropsClone.hasChildren = "has-children");
  const toFontEndReg = /(?=[A-Z])/;
  const strategy = {
    FontEnd: (str) => {
      return str.split(toFontEndReg).join("-").toLowerCase();
    },
    BackEnd: (str) => {
      return str
        .split("-")
        .map((el, idx) => {
          if (idx > 0) {
            return el.replace(el[0], el[0].toUpperCase());
          } else {
            return el;
          }
        })
        .join("");
    },
    FirstUppercase: (str) => {
      return str
        .split("-")
        .map((el, idx) => {
          return el.replace(el[0], el[0].toUpperCase());
        })
        .join("");
    },
  };
  if (u_getTypeof(data) === "object") {
    const orgKeys = Object.keys(data);
    const result = {};
    orgKeys.forEach((key) => {
      const newKey = strategy[target](key);
      const isContinueRecursion =
        u_getTypeof(data[key]) === "array" &&
        data[key].length > 0 &&
        isRecursion &&
        !safeKeys.includes(key);
      result[newKey] = isContinueRecursion
        ? mapKeysToTarget(data[key], target, isRecursion, treeProps)
        : data[key];
    });
    return result;
  } else if (u_getTypeof(data) === "array" && data.length > 0 && !isRecursion) {
    // 普通数组
    const orgKeys = Object.keys(data[0]);
    const results = [];
    data.map((el) => {
      const result = {};
      orgKeys.forEach((key) => {
        const newKey = strategy[target](key);
        result[newKey] = el[key];
      });
      results.push(result);
    });
    return results;
  } else if (u_getTypeof(data) === "string") {
    return strategy[target](data);
  } else if (
    u_getTypeof(data) === "array" &&
    data.length > 0 &&
    isRecursion &&
    data.every((el) => typeof el === "object")
  ) {
    // 树形数组则递归
    let orgKeys = [];
    //非树形递归
    if (Object.keys(treeProps).length === 0) {
      orgKeys = Array.from(new Set([...Object.keys(data[0])]));
    } else {
      //树形递归
      orgKeys = Array.from(
        new Set([
          ...Object.keys(data[0]),
          treePropsClone["children"],
          treePropsClone["hasChildren"],
        ])
      );
    }
    const results = [];
    data.map((el) => {
      const result = {};
      orgKeys.forEach((key) => {
        const newKey = strategy[target](key);
        if (key === treePropsClone["children"]) {
          result[newKey] = mapKeysToTarget(
            el[key],
            target,
            isRecursion,
            treePropsClone
          );
        } else if (u_getTypeof(el[key]) === "array" && data.length > 0) {
          result[newKey] = mapKeysToTarget(
            el[key],
            target,
            isRecursion,
            treeProps
          );
        } else {
          result[newKey] = el[key];
        }
      });
      results.push(result);
    });
    return results;
  } else {
    return data;
  }
}
/**
 * 简化版获取命名类型
 */
export const getNamingType = (name) => {
  const upperCaseReg = /([A-Z])/;
  if (upperCaseReg.test(name[0])) {
    return "Pascal";
  } else if (name.indexOf("-") !== -1) {
    return "Kebab";
  } else if (name.indexOf("_") !== -1) {
    return "Snake";
  } else {
    return "Camel";
  }
};
/**
 * 命名类型转换
 * 支持：Camel小驼峰、Pascal大驼峰、Snake下划线、Kebab中划线
 * @param {string} name 原变量名
 * @param {string | ""} fromNamingRule 原变量命名规则;为空则自动根据getNamingType推导
 * @param {string} toNamingRule 目标变量命名规则
 * */
export function transName(name, fromNamingRule, toNamingRule) {
  const curNaming = getNamingType(name);
  if (curNaming === toNamingRule) {
    return name;
  }
  if (!fromNamingRule) {
    fromNamingRule = curNaming;
  }
  // 对应命名类型的转换规则
  const NamingRules = {
    // 小驼峰
    Camel: {
      // 把对应命名规则的命名转换成数组状态
      ArrayState: (name) => {
        return name
          .replace(/([A-Z])/g, "-$1")
          .toLowerCase()
          .split("-");
      },
      // 把数组状态转化成对应命名规则的命名
      TransToTargetNaming: (arrayState) => {
        let result = "";
        arrayState.forEach((el, idx) => {
          if (idx === 0) {
            result += el;
          } else {
            result += el.replace(el[0], el[0].toUpperCase());
          }
        });
        return result;
      },
    },
    // 大驼峰
    Pascal: {
      ArrayState: (name) => {
        name = name[0] ? name.replace(name[0], name[0].toUpperCase()) : "";
        return name
          .replace(/([A-Z])/g, "-$1")
          .toLowerCase()
          .split("-")
          .splice(1);
      },
      TransToTargetNaming: (arrayState) => {
        let result = "";
        arrayState.forEach((el, idx) => {
          result += el.replace(el[0], el[0].toUpperCase());
        });
        return result;
      },
    },
    // 下划线
    Snake: {
      ArrayState: (name) => {
        return name.toLowerCase().split("_");
      },
      TransToTargetNaming: (arrayState) => {
        const result = arrayState.join("_");
        return result;
      },
    },
    // 中划线
    Kebab: {
      ArrayState: (name) => {
        return name.toLowerCase().split("-");
      },
      TransToTargetNaming: (arrayState) => {
        const result = arrayState.join("-");
        return result;
      },
    },
  };
  const arrayStateVal = NamingRules[fromNamingRule]["ArrayState"](name);
  const result =
    NamingRules[toNamingRule]["TransToTargetNaming"](arrayStateVal);
  return result;
}

/**
 * 根据key 获取地址栏query的value
 */
export function getQueryString(name) {
  var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
  let searchStr = "";
  if (window.location.search) {
    searchStr = window.location.search.substring(1);
  } else {
    const flagIdx = window.location.hash.indexOf("?");
    if (flagIdx !== -1) {
      searchStr = window.location.hash.substring(flagIdx + 1);
    }
  }
  var r = searchStr.match(reg);
  if (r != null) return decodeURIComponent(decodeURIComponent(r[2]));
  return null;
}

/**
 * 防抖
 * @param {Function} func
 * @param {int} wait 延时毫秒
 * @param {Boolean} immediate 是否立即执行
 * @returns {Function}
 */
export function debounce(func, wait = 1000, immediate = true) {
  let timeout;
  return function () {
    const context = this;
    const args = [...arguments];
    if (timeout) clearTimeout(timeout);
    if (immediate) {
      const callNow = !timeout;
      timeout = setTimeout(() => {
        timeout = null;
      }, wait);
      if (callNow) func.apply(context, args);
    } else {
      timeout = setTimeout(() => {
        func.apply(context, args);
      }, wait);
    }
  };
}

/**
 * 节流
 * @param {Function} func
 * @param {int} wait 延时毫秒
 * @returns {Function}
 */
export function throttle(func, wait = 1000) {
  let timeout;
  return function () {
    let context = this;
    let args = arguments;
    if (!timeout) {
      timeout = setTimeout(() => {
        timeout = null;
        func.apply(context, args);
      }, wait);
    }
  };
}

function traversalAllChild(dom) {
  var len = dom.length;
  var d = null;
  for (var i = 0; i < len; i++) {
    d = dom[i];
    console.log(d);
    if (d.children) {
      traversalAllChild(d.children);
    }
  }
}

/* 动态import组件 */
/* export function dynmicImport(filePath, rootPathType = "pages") {
  if (rootPathType === "pages") {
    return Promise.resolve(() => import(`@/pages/${filePath}`)); //require(`@/pages/${filePath}`)
  } else {
    return Promise.resolve(() => import(`@/components/${filePath}`)); //require(`@/components/${filePath}`)
  }
} */

/**
 * 状态机模式,重构 if-else等场景
 */
export class StateHandler {
  constructor({ initState = "", stateActionMapping = {} }) {
    this._currState = initState;
    this._stateAction = stateActionMapping;
  }
  changeState(currState) {
    this._currState = currState;
  }
  execAction({ actionName = "", params = {} }) {
    if (typeof actionName === "string") {
      const currStateActionMapping = this._stateAction[this._currState];
      if (currStateActionMapping.hasOwnProperty(actionName)) {
        currStateActionMapping[actionName](params);
      } else if (currStateActionMapping.hasOwnProperty("_DEFAULT")) {
        currStateActionMapping["_DEFAULT"](params);
      }
    } else if (Array.isArray(actionName)) {
      actionName.forEach((e) => {
        this.execAction({ actionName: e, params });
      });
    }
  }
}
export class StateHandler2 {
  constructor({
    initStateChain = [],
    stateActionMapping = {},
    excludeDefaultActionKeys = [],
    endingCallback = (params) => {},
  }) {
    //存储当前待执行的动作 们
    this._currentstate = {};
    this._stateAction = stateActionMapping;
    this._endingCallback = endingCallback;
    this.changeState(initStateChain);
  }
  //添加动作
  changeState(stateChain) {
    //清空当前的动作集合
    this._currentstate = {};
    //遍历添加动作
    stateChain.forEach((state) => (this._currentstate[state] = true));
    return this;
  }
  /** 串行执行动作 */
  execInSerial(params) {
    //当前动作集合中的动作依次执行
    const hasDefaultAction = this._currentstate.hasOwnProperty("_DEFAULT");
    Object.keys(this._currentstate).forEach((k) => {
      if (typeof this._stateAction[k] === "function") {
        this._stateAction[k](params);
      } else if (hasDefaultAction) {
        this._stateAction["_DEFAULT"](params);
      }
    });
    this._endingCallback(params);
    return this;
  }
  /** 聚合执行动作 */
  execInAggregation(params) {
    const hasDefaultAction = this._currentstate.hasOwnProperty("_DEFAULT");
    const aggregationActionKey = Object.keys(this._currentstate).join(".");
    if (typeof this._stateAction[aggregationActionKey] === "function") {
      this._stateAction[aggregationActionKey](params);
    } else if (hasDefaultAction) {
      this._stateAction["_DEFAULT"](params);
    }
    this._endingCallback(params);
    return this;
  }
}
///////////////////////////////////

///////////////////
//数字格式相关
/** 保留小数数点后几位 */
export const numToFix = (val, n, isPatchZero = true) => {
  let ratio = 1;
  for (let i = 0; i < n; i++) {
    ratio *= 10;
  }
  let retVal = Math.floor(val * ratio) / ratio;
  //补零
  if (n > 0 && isPatchZero) {
    const splitVals = `${retVal}`.split(".");
    let patchZeroNum = 0;
    if (splitVals.length === 1) {
      retVal += ".";
      patchZeroNum = n;
    }
    if (splitVals.length === 2 && splitVals[1].length < n) {
      patchZeroNum = n - splitVals[1].length;
    }
    for (let i = 0; i < patchZeroNum; i++) {
      retVal += "0";
    }
  }
  //补零
  return retVal;
};
////////////////
//其它工具类
/**
 * 获取地址栏的path
 */
export const getUrlPath = () => {
  return globalConfig.ROUTER_MODE === "hash"
    ? location.pathname
    : location.pathname.replace(globalConfig.BASE_ROUTER_PREFIX_PATH, "");
};
